using System;
using UnityEngine;

public class CharacterRotationController : MonoBehaviour
{
	[Serializable]
	public class RotationControllerSettings
	{
		public bool useHorizontalLimits;

		public FloatRange horizontalAngleLimits;

		public bool useVerticalLimits = true;

		public FloatRange verticalAngleLimits = new FloatRange
		{
			min = -30f,
			max = 30f
		};

		public FloatRange extension = new FloatRange
		{
			min = 0.2f,
			max = 0f
		};

		public FloatRange extensionAngleRange = new FloatRange
		{
			min = -30f,
			max = 0f
		};
	}

	public GameObject playerModel;

	private Camera displayCamera;

	public float cameraMoveSpeed = 1f;

	public float cameraRotationSpeed = 1f;

	private bool enableRotation;

	private Vector3 rot;

	private Vector3 rotVelocity;

	private bool rotStarted;

	private Vector3 inPoint;

	private float finX;

	private Vector3 curPoint;

	private Vector3 point;

	public float speed = 0.1f;

	public float friction = 1.5f;

	private Transform rotationTransform;

	public Vector3 lookAtPoint;

	private Vector3 startPosition;

	private Quaternion startRotation;

	private RotationControllerSettings settings = new RotationControllerSettings();

	public static CharacterRotationController instance { get; protected set; }

	private void Init()
	{
	}

	private void Awake()
	{
		instance = this;
	}

	private void OnDestroy()
	{
		instance = null;
	}

	public void SetRotationEnabled(Camera displayCamera, Transform transformToRotate, RotationControllerSettings settings, bool isEnabled)
	{
		if (settings != null)
		{
			this.settings = settings;
		}
		Debug.Log("Set Rotation Enabled");
		this.displayCamera = displayCamera;
		rotationTransform = transformToRotate;
		if (transformToRotate != null)
		{
			startPosition = transformToRotate.position;
			startRotation = transformToRotate.rotation;
			Vector3 vector = (playerModel.transform.position - startPosition).OnGround();
			lookAtPoint = startPosition + transformToRotate.forward * vector.magnitude / Vector3.Dot(transformToRotate.forward.normalized, vector.normalized);
		}
		if (!isEnabled && rotationTransform != null)
		{
			Debug.Log(string.Concat("transform to rotate ", rotationTransform, " displayCamera ", displayCamera));
			displayCamera.transform.position = rotationTransform.position;
			displayCamera.transform.rotation = rotationTransform.rotation;
		}
		rotVelocity = (rot = Vector3.zero);
		enableRotation = isEnabled;
		rotStarted = false;
	}

	private void RotateAround(Transform t1, Vector3 startPosition, Quaternion startRotation, Vector3 aroundPoint, Quaternion rotation, float extension)
	{
		Vector3 vector = startPosition - aroundPoint;
		t1.position = aroundPoint + rotation * (vector + vector.normalized * extension);
		t1.rotation = rotation * startRotation;
	}

	private void Update()
	{
		if (InputControl.buttonDown && enableRotation)
		{
			point = displayCamera.ScreenToViewportPoint(Input.mousePosition);
			bool flag = point.x >= 0f && point.x <= 1f && point.y >= 0f && point.y <= 1f && point.z >= 0f && point.z <= 1f;
			rotStarted = flag;
			inPoint = Input.mousePosition;
		}
		if (!enableRotation)
		{
			rotStarted = false;
		}
		if (rotStarted)
		{
			curPoint = Input.mousePosition;
			rotVelocity.x = (curPoint.x - inPoint.x) * 360f / (float)Screen.width;
			rotVelocity.y = (curPoint.y - inPoint.y) * 90f / (float)Screen.height;
		}
		if (!InputControl.mouseButton && enableRotation)
		{
			rotVelocity /= friction;
			rotStarted = false;
		}
		if (Mathf.Abs(rotVelocity.x) > 0.2f || Mathf.Abs(rotVelocity.y) > 0.2f)
		{
			rot += rotVelocity;
			if (settings.useVerticalLimits)
			{
				rot.y = settings.verticalAngleLimits.Clamp(rot.y);
			}
			if (settings.useHorizontalLimits)
			{
				rot.x = settings.horizontalAngleLimits.Clamp(rot.x);
			}
			inPoint = curPoint;
			float extension = settings.extension.Lerp(settings.extensionAngleRange.InverseLerp(rot.y));
			Quaternion rotation = Quaternion.AngleAxis(rot.x, Vector3.up) * Quaternion.AngleAxis(rot.y, Vector3.Cross((lookAtPoint - startPosition).OnGround(), Vector3.up));
			RotateAround(displayCamera.transform, startPosition, startRotation, lookAtPoint, rotation, extension);
			RotateAround(rotationTransform, startPosition, startRotation, lookAtPoint, rotation, extension);
		}
		if (!(displayCamera == null) && !(rotationTransform == null))
		{
			displayCamera.transform.position = Vector3.Lerp(displayCamera.transform.position, rotationTransform.position, cameraMoveSpeed * Time.deltaTime);
			displayCamera.transform.rotation = Quaternion.Lerp(displayCamera.transform.rotation, rotationTransform.rotation, cameraRotationSpeed * Time.deltaTime);
		}
	}
}
